﻿using DataDefine;
using ECANPort;
using TLDNs.ViewModels.DateFrames;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UsingEventAggregator.Core;

namespace TLDNs.ViewModels
{

    namespace DateFrames
    {
        /// <summary>
        /// 被动接收数据帧
        /// </summary>
        public class PassivityDataFrame
        {
            public uint CanID { get; set; }
            public int DeviceIndex;
            public int ParameterIndex;
            public byte[] Data;
            public PassivityDataFrame(uint id)
            {
                CanID = id;
                Data = new byte[8];
            }
        }


        public class ZhuDriveFaultCodeFrame : PassivityDataFrame
        {
            public ZhuDriveFaultCodeFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public byte FaultCode
            {
                get { return Data[1]; }
                set { Data[1] = value; }
            }
        }

        public class ZhuDriveSWFrame : PassivityDataFrame
        {
            public ZhuDriveSWFrame(uint id) : base(id)
            {
                CanID = id;
            }

            private bool[] SWs = new bool[16];
            public bool GetSW(int index)
            {
                if (index >= 0 && index < 16)
                {
                    ushort tmp = (ushort)((Data[1] << 8) + Data[0]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }

            private bool[] Drivers = new bool[5];
            public bool GetDrivers(int index)
            {
                if (index >= 0 && index < 5)
                {
                    ushort tmp = (ushort)(Data[2]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }

            public byte Drive_State { get { return Data[3]; } }

            /// <summary>
            /// 皮带
            /// </summary>
            public ushort Belt_HM { get { return (ushort)(Data[4] + (Data[5] << 8)); } }

            /// <summary>
            /// 牵引
            /// </summary>
            public ushort Traction_HM { get { return (ushort)(Data[6] + (Data[7] << 8)); } }
        }
        public class ZhuDriveKeyswitchFrame : PassivityDataFrame
        {
            public ZhuDriveKeyswitchFrame(uint id) : base(id)
            {

            }
            public ushort Keyswitch_Voltage { get { return (ushort)(Data[0] + (Data[1] << 8)); } }
            public ushort Current_RMS { get { return (ushort)(Data[2] + (Data[3] << 8)); } }
            public ushort Battery_Current { get { return (ushort)(Data[4] + (Data[5] << 8)); } }
            public ushort Motor_RPM { get { return (ushort)(Data[6] + (Data[7] << 8)); } }

        }

        public class ZhuDriveStatusFrame : PassivityDataFrame
        {
            public ZhuDriveStatusFrame(uint id) : base(id)
            {
                CanID = id;
            }

            public byte GetStatus(int index)
            {
                if (index >= 0 && index < 7)
                {
                    return Data[index];
                }
                return 0;
            }

            public byte WholeFault { get { return Data[7]; } }
        }

        public class ZhuDriveGeneralHMFrame : PassivityDataFrame
        {
            public ZhuDriveGeneralHMFrame(uint id) : base(id)
            {
                CanID = id;
            }

            public ushort GeneralHM { get { return (ushort)(Data[0] + (Data[1] << 8)); } }
            /// <summary>
            /// 00 12 C3 A3  十六进制
            /// 00 18 195 163  十进制
            /// </summary>
            public uint V1229731
            {
                get
                {
                    uint tmp = 0;
                    tmp += Data[2];
                    tmp += (uint)(Data[3] << 8);
                    tmp += (uint)(Data[4] << 16);
                    tmp += (uint)(Data[5] << 24);
                    return tmp;
                }
            }
            public byte A { get { return Data[6]; } }
            public byte BDIPercentage { get { return Data[7]; } }
        }

        public class ZhuDriveTrottleCommandFrame : PassivityDataFrame
        {
            public ZhuDriveTrottleCommandFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public bool 启动泵 { get { return (Data[0] & 1) > 0; } }
            public bool Handbrake_sw或低电量 { get { return (Data[0] & 2) > 0; } }
            public bool 无方向 { get { return (Data[0] & 4) > 0; } }
            public ushort Trottle_Command { get { return (ushort)(Data[1] + (Data[2] << 8)); } }

        }

        public class ZhuDriveSW2Frame : PassivityDataFrame
        {
            public ZhuDriveSW2Frame(uint id) : base(id)
            {
                CanID = id;
            }
            public byte FaultCode
            {
                get { return Data[1]; }
                set { Data[1] = value; }
            }

            private bool[] SWs = new bool[16];
            public bool GetSW(int index)
            {
                if (index >= 0 && index < 16)
                {
                    ushort tmp = (ushort)((Data[1] << 8) + Data[0]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }
            public int qM_ZONE { get { return (Data[7] & 1); } }
        }


        public class PumpSWFrame : PassivityDataFrame
        {
            public PumpSWFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public byte FaultCode
            {
                get { return Data[1]; }
                set { Data[1] = value; }
            }

            private bool[] SWs = new bool[16];
            public bool GetSW(int index)
            {
                if (index >= 0 && index < 16)
                {
                    ushort tmp = (ushort)((Data[1] << 8) + Data[0]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }

            private bool[] Drivers = new bool[5];
            public bool GetDrivers(int index)
            {
                if (index >= 0 && index < 5)
                {
                    ushort tmp = (ushort)(Data[2]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }

            public byte Drive_State { get { return Data[3]; } }
            public byte Controller_Status { get { return Data[4]; } }

        }

        public class PumpDriveSW2Frame : PassivityDataFrame
        {
            public PumpDriveSW2Frame(uint id) : base(id)
            {
                CanID = id;
            }
            public byte FaultCode
            {
                get { return Data[1]; }
                set { Data[1] = value; }
            }

            private bool[] SWs = new bool[16];
            public bool GetSW(int index)
            {
                if (index >= 0 && index < 16)
                {
                    ushort tmp = (ushort)((Data[1] << 8) + Data[0]);
                    return (tmp & (1 << index)) > 0;
                }
                return false;
            }
        }

    }

    /// <summary>
    /// 主控制器-被动接收-可控制暂停发送
    /// </summary>
    public class ZhuDrive
    {
        public const uint ZhuDriveHMICanID = 0X0F1;
        public const int DeviceIndex = 0;
        /// <summary>
        /// 总数据个数 = 被动接收 + 可主动读写数据  (解析后的独立定义的·数据)
        /// </summary>
        public const int DataItemCount = 60 + 128;
        /// <summary>
        /// 被动接收数据个数
        /// </summary>
        public const int PassivityDataItemCount = 60;
        public const int HMIZhuDriveStart = 60;



        public static List<uint> CanIDList = new List<uint>();
        public Dictionary<uint, object> ObjDic = new Dictionary<uint, object>();

        public PassivityDataFrame FaultCode { get; set; }
        public ZhuDriveSWFrame SW { get; set; }
        public ZhuDriveKeyswitchFrame Keyswitc { get; set; }
        public ZhuDriveStatusFrame Status { get; set; }
        public ZhuDriveGeneralHMFrame GeneralHM { get; set; }
        public ZhuDriveTrottleCommandFrame Trottle { get; set; }
        public ZhuDriveSW2Frame SW2 { get; set; }
        public PassivityDataFrame BMS_TO_CANbus { get; set; }
        public PassivityDataFrame FF_TO_BMS { get; set; }

        static ZhuDrive()
        {
            CanIDList.Clear();
            CanIDList.Add(0x1A5);
            CanIDList.Add(0x1A6);
            CanIDList.Add(0x2A6);
            CanIDList.Add(0x3A6);
            CanIDList.Add(0x4A6);
            CanIDList.Add(0x227);
            CanIDList.Add(0x1B1);
            CanIDList.Add(0x2F0);
            CanIDList.Add(0x20A);
        }

        public ZhuDrive()
        {
            ObjDic.Clear();
            FaultCode = new ZhuDriveFaultCodeFrame(0x1A5);
            SW = new ZhuDriveSWFrame(0x1A6);
            Keyswitc = new ZhuDriveKeyswitchFrame(0x2A6);
            Status = new ZhuDriveStatusFrame(0x3A6);
            GeneralHM = new ZhuDriveGeneralHMFrame(0x4A6);
            Trottle = new ZhuDriveTrottleCommandFrame(0x227);
            SW2 = new ZhuDriveSW2Frame(0x1B1);
            BMS_TO_CANbus = new PassivityDataFrame(0x2F0);
            FF_TO_BMS = new PassivityDataFrame(0x20A);
            ObjDic.Add(0x1A5, FaultCode);
            ObjDic.Add(0x1A6, SW);
            ObjDic.Add(0x2A6, Keyswitc);
            ObjDic.Add(0x3A6, Status);
            ObjDic.Add(0x4A6, GeneralHM);
            ObjDic.Add(0x227, Trottle);
            ObjDic.Add(0x1B1, SW2);
            ObjDic.Add(0x2F0, BMS_TO_CANbus);
            ObjDic.Add(0x20A, FF_TO_BMS);

        }


    }

    /// <summary>
    /// 油泵控制器-被动接收-可控制暂停发送
    /// </summary>
    public class Pump
    {

        public const uint PumpHMICanID = 0X0F3;
        /// <summary>
        /// 总数据个数 = 被动接收 + 可主动读写数据  (解析后的独立定义的·数据)
        /// </summary>
        public const int DataItemCount = 60 + 128;
        /// <summary>
        /// 被动接收数据个数
        /// </summary>
        public const int PassivityDataItemCount = 60;
        public const int HMIPumpStart = 60;

        public const int DeviceIndex = 1;
        public static List<uint> CanIDList = new List<uint>();
        public Dictionary<uint, object> ObjDic = new Dictionary<uint, object>();
        public ZhuDriveFaultCodeFrame FaultCode { get; set; }
        public PumpSWFrame SW { get; set; }
        public ZhuDriveKeyswitchFrame Keyswitc { get; set; }
        public ZhuDriveStatusFrame Status { get; set; }
        public ZhuDriveGeneralHMFrame GeneralHM { get; set; }
        public ZhuDriveTrottleCommandFrame Trottle { get; set; }
        public PumpDriveSW2Frame SW2 { get; set; }

        static Pump()
        {
            CanIDList.Add(0x1A7);
            CanIDList.Add(0x1A8);
            CanIDList.Add(0x2A8);
            CanIDList.Add(0x3A8);
            CanIDList.Add(0x4A8);
            CanIDList.Add(0x2B1);
        }

        public Pump()
        {
            ObjDic.Clear();
            FaultCode = new ZhuDriveFaultCodeFrame(0x1A7);
            SW = new PumpSWFrame(0x1A8);
            Keyswitc = new ZhuDriveKeyswitchFrame(0x2A8);
            Status = new ZhuDriveStatusFrame(0x3A8);
            GeneralHM = new ZhuDriveGeneralHMFrame(0x4A8);
            SW2 = new PumpDriveSW2Frame(0x2B1);

            ObjDic.Add(0x1A7, FaultCode);
            ObjDic.Add(0x1A8, SW);
            ObjDic.Add(0x2A8, Keyswitc);
            ObjDic.Add(0x3A8, Status);
            ObjDic.Add(0x4A8, GeneralHM);
            ObjDic.Add(0x2B1, SW2);
        }

    }

    /// <summary>
    /// 电池-被动接收-无法控制
    /// </summary>
    public class BMS
    {
        public const int DataItemCount = 30;
        public const int DeviceIndex = 2;
        public static List<uint> CanIDList = new List<uint>();
        public Dictionary<uint, object> ObjDic = new Dictionary<uint, object>();

        public MBS_2F0_DataFrame MBS_2F0 { get; set; }

        public MBS_20A_DataFrame MBS_20A { get; set; }
        public MBS_20B_DataFrame MBS_20B { get; set; }

        public MBS_2F1_DataFrame MBS_2F1 { get; set; }
        public MBS_2F2_DataFrame MBS_2F2 { get; set; }
        public MBS_2F3_DataFrame MBS_2F3 { get; set; }

        public MBS_326_DataFrame MBS_326 { get; set; }

        static BMS()
        {
            CanIDList.Add(0x2F0);

            CanIDList.Add(0x20A);
            CanIDList.Add(0x20B);

            CanIDList.Add(0x2F1);
            CanIDList.Add(0x2F2);
            CanIDList.Add(0x2F3);

            CanIDList.Add(0x326);
        }

        public BMS()
        {
            ObjDic.Clear();
            MBS_2F0 = new MBS_2F0_DataFrame(0x2F0);


            MBS_20A = new MBS_20A_DataFrame(0x20A);
            MBS_20B = new MBS_20B_DataFrame(0x20B);

            MBS_2F1 = new MBS_2F1_DataFrame(0x2F1);
            MBS_2F2 = new MBS_2F2_DataFrame(0x2F2);
            MBS_2F3 = new MBS_2F3_DataFrame(0x2F3);

            MBS_326 = new MBS_326_DataFrame(0x326);

            ObjDic.Add(0x2F0, MBS_2F0);

            ObjDic.Add(0x20A, MBS_20A);
            ObjDic.Add(0x20B, MBS_20B);

            ObjDic.Add(0x2F1, MBS_2F1);
            ObjDic.Add(0x2F2, MBS_2F2);
            ObjDic.Add(0x2F3, MBS_2F3);

            ObjDic.Add(0x326, MBS_326);
        }




        public class MBS_2F0_DataFrame : PassivityDataFrame
        {

            public static int GetStatusValue(MBSStatus Status, MBSStatus tag)
            {
                return Status.HasFlag(tag) ? 1 : 0;
            }




            public MBS_2F0_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }

            [Flags]
            public enum MBSStatus : byte
            {
                OverVoltage = 1,
                CellLowVoltage = 2,
                DIFFERENCE = 4,
                OverallVoltageLow = 8,
                TempOutOfRange = 32,
                BatteryFault = 64,
                ToShutdown = 128,
            }


            public ushort Ubus { get { return (ushort)(Data[0] + Data[1] * 256); } }
            public ushort IBattery { get { return (ushort)(Data[2] + Data[3] * 256); } }
            public byte SOC { get { return Data[4]; } }
            public byte Capacity { get { return Data[5]; } }

            public MBSStatus Status { get { return (MBSStatus)Data[6]; } }
            public bool OverVoltage { get { return Status.HasFlag(MBSStatus.OverVoltage); } }
            public bool CellLowVoltage { get { return Status.HasFlag(MBSStatus.CellLowVoltage); } }
            public bool DIFFERENCE { get { return Status.HasFlag(MBSStatus.DIFFERENCE); } }
            public bool OverallVoltageLow { get { return Status.HasFlag(MBSStatus.OverallVoltageLow); } }
            public bool TempOutOfRange { get { return Status.HasFlag(MBSStatus.TempOutOfRange); } }
            public bool BatteryFault { get { return Status.HasFlag(MBSStatus.BatteryFault); } }
            public bool ToShutdown { get { return Status.HasFlag(MBSStatus.ToShutdown); } }

            public byte ErrorLv { get { return Data[7]; } }
        }

        public class MBS_20A_DataFrame : PassivityDataFrame
        {
            public MBS_20A_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            /// <summary>
            /// 通信标准
            /// 0xAA
            /// 0xA5 手动加热
            /// </summary>
            public byte CANCommNormal { get { return Data[0]; } }
        }
        public class MBS_20B_DataFrame : PassivityDataFrame
        {
            public MBS_20B_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public byte PackParallelNumber { get { return Data[0]; } }
            public byte PackSeriesNumber { get { return Data[1]; } }
            public byte ChargerType { get { return Data[2]; } }

        }

        public class MBS_2F1_DataFrame : PassivityDataFrame
        {
            public MBS_2F1_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public ushort Umaxcell { get { return (ushort)(Data[0] + Data[1] * 256); } }
            public byte UmaxcellPosition1 { get { return Data[2]; } }
            public byte UmaxcellPosition2 { get { return Data[3]; } }
            public ushort Umincell { get { return (ushort)(Data[4] + Data[5] * 256); } }
            public byte UmincellPosition1 { get { return Data[6]; } }
            public byte UmincellPosition2 { get { return Data[7]; } }
        }
        public class MBS_2F2_DataFrame : PassivityDataFrame
        {
            public MBS_2F2_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public ushort Tmaxcell { get { return (ushort)(Data[0] + Data[1] * 256); } }
            public byte TmaxcellPosition1 { get { return Data[2]; } }
            public byte TmaxcellPosition2 { get { return Data[3]; } }
            public ushort Tmincell { get { return (ushort)(Data[4] + Data[5] * 256); } }
            public byte TmincellPosition1 { get { return Data[6]; } }
            public byte TmincellPosition2 { get { return Data[7]; } }
        }
        public class MBS_2F3_DataFrame : PassivityDataFrame
        {
            public MBS_2F3_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public ushort DischargeHours { get { return (ushort)(Data[0] + Data[1] * 256); } }
            public ushort ChargeHours { get { return (ushort)(Data[2] + Data[3] * 256); } }
            public byte RelaysFlag { get { return Data[4]; } }
            public byte PacksSafetyFlag { get { return Data[5]; } }
            public byte PacksStatusFlag { get { return Data[6]; } }
            public byte PLCFaultCode { get { return Data[7]; } }
        }

        public class MBS_326_DataFrame : PassivityDataFrame
        {
            public MBS_326_DataFrame(uint id) : base(id)
            {
                CanID = id;
            }
            public ushort MaxDischargeCurrent { get { return (ushort)(Data[0] + Data[1] * 256); } }
            public ushort MaxFeedbackCurrent { get { return (ushort)(Data[2] + Data[3] * 256); } }
        }


    }

}


namespace TLDNs.ViewModels
{

    public enum Can_Fc : byte
    {
        /// <summary>
        /// 单击断开连接前发送一次
        /// </summary>
        RecoverCANnode = 0,

        /// <summary>
        /// 发送这一帧后（主控制器和Pump）停止其他数据发送
        /// </summary>
        StopCANtx = 1,

        /// <summary>
        /// 发一次后，返回一次 2  7
        /// </summary>
        Read = 7,

        /// <summary>
        /// 发一次后，返回一次 3  9
        /// </summary>
        Write = 9,

        MultiWrite = 4,

        /// <summary>
        /// 发送这一帧后（主控制器和Pump）恢复其他数据发送
        /// </summary>
        RelaseCanBus = 5,

        ErrCommand = 6,

        /// <summary>
        /// 另外一个数组(地址重新从0开始)，发一次后，返回一次
        /// </summary>
        HMI_读单个 = 77,

        /// <summary>
        /// 需要地址连续
        /// 另外一个数组(地址重新从0开始)，发一次后，返回很多次
        /// 读字节数可以大于4
        /// </summary>
        HMI_读多个 = 8,
        /// <summary>
        /// 另外一个数组(地址重新从0开始)，发一次后，返回一次
        /// </summary>
        HMI_写单个 = 99,

    }
    /// <summary>
    /// 主动模式-可主动读写主控制器和油泵控制器
    /// </summary>
    public static class HMIHelper
    {
        //public const uint ZhuDriveCanID = 0X0F1;
        //public const uint PumpCanID = 0X0F3;


        /// <summary>
        /// HMI数据帧
        /// </summary>
        public class HMIDateFrame
        {
            public byte ID { get; set; }
            public Can_Fc Can_Fc { get; set; }
            public byte Addr_Start { get; set; }
            public byte ByteCount { get; set; }
            public byte[] Data0 { get; set; }

            public HMIDateFrame()
            {

            }
            public HMIDateFrame(byte[] data8)
            {
                if (data8.Length >= 8)
                {
                    ID = data8[0];
                    Can_Fc = (Can_Fc)data8[1];
                    Addr_Start = data8[2];
                    ByteCount = data8[3];
                    if (ByteCount >= 4)
                        ByteCount = 4;
                    Data0 = new byte[ByteCount];
                    for (int i = 0; i < ByteCount; i++)
                    {
                        Data0[i] = data8[4 + i];
                    }


                }
            }
            public static HMIDateFrame CreateReadFrame(byte addr, byte Count)
            {
                HMIDateFrame tmp = new HMIDateFrame();
                tmp.Can_Fc = Can_Fc.Read;
                tmp.Addr_Start = addr;
                if (Count > 4)
                    Count = 4;
                tmp.ByteCount = Count;
                return tmp;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="addr"></param>
            /// <param name="Count">Max254</param>
            /// <returns></returns>
            public static HMIDateFrame CreateHMIRead8Frame(byte addr, byte Count)
            {
                HMIDateFrame tmp = new HMIDateFrame();
                tmp.Can_Fc = Can_Fc.HMI_读多个;
                tmp.Addr_Start = addr;
                tmp.ByteCount = Count;
                return tmp;
            }

            public static HMIDateFrame CreateStopCANtxFrame()
            {
                HMIDateFrame tmp = new HMIDateFrame();
                tmp.Can_Fc = Can_Fc.StopCANtx;
                tmp.Addr_Start = 0;
                tmp.ByteCount = 2;
                return tmp;
            }
            public static HMIDateFrame CreateRelaseCanBusFrame()
            {
                HMIDateFrame tmp = new HMIDateFrame();
                tmp.Can_Fc = Can_Fc.RelaseCanBus;
                tmp.Addr_Start = 0;
                tmp.ByteCount = 2;
                return tmp;
            }
            public static HMIDateFrame CreateWriteFrame(byte addr, byte ByteCount, byte[] data)
            {
                HMIDateFrame tmp = new HMIDateFrame();
                tmp.Can_Fc = Can_Fc.Write;
                tmp.Addr_Start = addr;
                if (ByteCount > 4)
                    ByteCount = 4;
                tmp.ByteCount = ByteCount;
                tmp.Data0 = data;
                return tmp;
            }
        }

        public static bool ReadWriteDataLenExtend8 = true;
        public static CAN_OBJ CreateRead(uint CanID, HMIDateFrame wd)
        {
            CAN_OBJ F = new CAN_OBJ();
            F.ID = CanID;
            F.RemoteFlag = 0;
            F.ExternFlag = 0;
            if (ReadWriteDataLenExtend8)
                F.DataLen = 8;
            else
                F.DataLen = 4;

            F.data = new byte[8];
            F.data[0] = wd.ID;
            F.data[1] = (byte)wd.Can_Fc;
            F.data[2] = wd.Addr_Start;
            F.data[3] = wd.ByteCount;
            F.Reserved = new byte[3];
            F.SendType = 0;
            return F;
        }
        public static CAN_OBJ CreateStopCANtxFrame(uint CanID, HMIDateFrame wd)
        {
            CAN_OBJ F = new CAN_OBJ();
            F.ID = CanID;
            F.RemoteFlag = 0;
            F.ExternFlag = 0;
            if (ReadWriteDataLenExtend8)
                F.DataLen = 8;
            else
                F.DataLen = 4;

            F.data = new byte[8];
            F.data[0] = wd.ID;
            F.data[1] = (byte)wd.Can_Fc;
            F.data[2] = wd.Addr_Start;
            F.data[3] = wd.ByteCount;
            F.Reserved = new byte[3];
            F.SendType = 0;
            return F;
        }


        public static CAN_OBJ CreateWrite(uint CanID, HMIDateFrame wd)
        {
            CAN_OBJ F = new CAN_OBJ();
            F.ID = CanID;
            F.RemoteFlag = 0;
            F.ExternFlag = 0;
            if (ReadWriteDataLenExtend8)
                F.DataLen = 8;
            else
                F.DataLen = (byte)(wd.ByteCount + 4);

            F.data = new byte[8];
            F.data[0] = wd.ID;
            F.data[1] = (byte)wd.Can_Fc;
            F.data[2] = wd.Addr_Start;
            F.data[3] = wd.ByteCount;
            F.Reserved = new byte[3];
            F.SendType = 0;

            for (int i = 0; i < wd.ByteCount; i++)
            {
                F.data[4 + i] = wd.Data0[0 + i];
            }

            return F;
        }

    }

    internal class ErrHisHelper
    {
        /// <summary>
        /// 带有故障信息的CanID
        /// 被动接收
        /// </summary>
        public static List<uint> ErrCanIDs = new List<uint>();

        public static List<(uint CanID, int Addr)> HMIErrCanIDs = new List<(uint CanID, int Addr)>();
        public static int HMIErrAddr1 = 71;
        public static int HMIErrAddr2 = 72;

        public static Dictionary<uint, int> CanID_DevNameDic = new Dictionary<uint, int>();

        public static IEventAggregator _ea;
        static ErrHisHelper()
        {
            ErrCanIDs.Clear();
            ErrCanIDs.Add(0x1A5);
            ErrCanIDs.Add(0x3A6);

            ErrCanIDs.Add(0x1A7);
            ErrCanIDs.Add(0x3A8);

            CanID_DevNameDic.Clear();
            CanID_DevNameDic.Add(0x1A5, 0);
            CanID_DevNameDic.Add(0x3A6, 0);

            CanID_DevNameDic.Add(0x1A7, 1);
            CanID_DevNameDic.Add(0x3A8, 1);

            CanID_DevNameDic.Add(0x2F0, 2);


            CanID_DevNameDic.Add(0X0F1, 0);
            CanID_DevNameDic.Add(0X0F3, 1);

            ErrCanIDs.Add(0X0F1);
            ErrCanIDs.Add(0X0F3);

            HMIErrCanIDs.Clear();
            HMIErrCanIDs.Add((0X0F1, 71));
            HMIErrCanIDs.Add((0X0F1, 72));

            HMIErrCanIDs.Add((0X0F3, 71));
            HMIErrCanIDs.Add((0X0F3, 72));
        }

        internal void Resolve(ref SFMDocument doc, CAN_OBJ info)
        {
            switch (info.ID)
            {
                case 0x1A5:
                    {
                        ZhuDriveFaultCodeFrame zhu = new ZhuDriveFaultCodeFrame(info.ID);
                        zhu.Data = info.data;
                        int DevIndex = CanID_DevNameDic[0x1A5];
                        CanNewErrorHistoryEvent.DevIndex = DevIndex;
                        CanNewErrorHistoryEvent.EErrClass = 1;
                        CanNewErrorHistoryEvent.ErrName = "Fault code";
                        CanNewErrorHistoryEvent.ErrAddInfo = "0x1A5  Fault code";
                        if (zhu.FaultCode > 0)
                            _ea.GetEvent<CanNewErrorHistoryEvent>().Publish((zhu.FaultCode, DevIndex));
                    }
                    break;
                case 0x3A6:
                    {
                        ZhuDriveStatusFrame zhu = new ZhuDriveStatusFrame(info.ID);
                        zhu.Data = info.data;
                        int DevIndex = CanID_DevNameDic[0x3A6];
                        CanNewErrorHistoryEvent.DevIndex = DevIndex;
                        CanNewErrorHistoryEvent.EErrClass = 1;
                        CanNewErrorHistoryEvent.ErrName = "Whole Fault";
                        CanNewErrorHistoryEvent.ErrAddInfo = "0x3A6 Whole Fault";
                        if (zhu.WholeFault > 0)
                            _ea.GetEvent<CanNewErrorHistoryEvent>().Publish((zhu.WholeFault, DevIndex));
                    }
                    break;
                case 0x1A7:
                    {
                        ZhuDriveFaultCodeFrame zhu = new ZhuDriveFaultCodeFrame(info.ID);
                        zhu.Data = info.data;
                        int DevIndex = CanID_DevNameDic[0x1A7];
                        CanNewErrorHistoryEvent.DevIndex = DevIndex;
                        CanNewErrorHistoryEvent.EErrClass = 1;
                        CanNewErrorHistoryEvent.ErrName = "Fault code";
                        CanNewErrorHistoryEvent.ErrAddInfo = "0x1A7 Fault code";
                        if (zhu.FaultCode > 0)
                            _ea.GetEvent<CanNewErrorHistoryEvent>().Publish((zhu.FaultCode, DevIndex));
                    }
                    break;
                case 0x3A8:
                    {
                        ZhuDriveStatusFrame zhu = new ZhuDriveStatusFrame(info.ID);
                        zhu.Data = info.data;
                        int DevIndex = CanID_DevNameDic[0x3A8];
                        CanNewErrorHistoryEvent.DevIndex = DevIndex;
                        CanNewErrorHistoryEvent.EErrClass = 1;
                        CanNewErrorHistoryEvent.ErrName = "Whole Fault";
                        CanNewErrorHistoryEvent.ErrAddInfo = "0x3A8  Whole Fault";
                        if (zhu.WholeFault > 0)
                            _ea.GetEvent<CanNewErrorHistoryEvent>().Publish((zhu.WholeFault, DevIndex));
                    }
                    break;
                case 0x2F0:
                    {
                        BMS.MBS_2F0_DataFrame zhu = new BMS.MBS_2F0_DataFrame(info.ID);
                        zhu.Data = info.data;
                        int DevIndex = CanID_DevNameDic[0x2F0];
                        CanNewErrorHistoryEvent.DevIndex = DevIndex;
                        CanNewErrorHistoryEvent.EErrClass = 1;
                        CanNewErrorHistoryEvent.ErrName = "MBS Err Status_Flag";
                        string addstr = zhu.Status.ToString("F");
                        CanNewErrorHistoryEvent.ErrAddInfo = addstr;
                        if ((byte)zhu.Status > 0)
                            _ea.GetEvent<CanNewErrorHistoryEvent>().Publish(((int)zhu.Status, DevIndex));
                    }
                    break;
                default:
                    break;
            }

            if (info.ID == 0X0F1 || info.ID == 0X0F3)
            {
                int DevIndex = CanID_DevNameDic[info.ID];
                HMIHelper.HMIDateFrame fr = new HMIHelper.HMIDateFrame(info.data);
                int addr = fr.Addr_Start / 2;
                if (fr.ByteCount >= 2 && fr.Data0.Length >= 2 && HMIErrCanIDs.Contains((info.ID, addr)))
                {
                    UInt32 err = (UInt32)(fr.Data0[0] + fr.Data0[1] * 256);
                    if (addr == HMIErrAddr2)
                        err = err << 16;

                    if (err > 0)
                        _ea.GetEvent<NewErrorHistoryEvent>().Publish((err, DevIndex));
                }
                if (fr.ByteCount >= 4 && fr.Data0.Length >= 4 && HMIErrCanIDs.Contains((info.ID, addr + 1)))
                {
                    uint err = (UInt32)(fr.Data0[2] + fr.Data0[3] * 256);
                    if (addr == HMIErrAddr2)
                        err = err << 16;

                    if (err > 0)
                        _ea.GetEvent<NewErrorHistoryEvent>().Publish((err, DevIndex));
                }
            }
        }

    }

    public class TLDCanDataSet
    {
        /// <summary>
        /// 总共3个设备
        /// ZhuDrive
        /// Pump
        /// BMS
        /// </summary>
        public const int CanDeviceCount = 3;

        public static byte[] ZhuDriveData;
        public static byte[] PumpData;
        public static byte[] BMSData;
        public static byte[] HMIData;


        public static SFMDocument InherDoc;

        static TLDCanDataSet()
        {
            InherDoc = TLDCanDataSet_CreateZero();
        }

        public static SFMDocument TLDCanDataSet_CreateZero()
        {
            int[] ParCount = new int[CanDeviceCount];
            ParCount[ZhuDrive.DeviceIndex] = ZhuDrive.DataItemCount;
            ParCount[Pump.DeviceIndex] = Pump.DataItemCount;
            ParCount[BMS.DeviceIndex] = BMS.DataItemCount;
            return SFMDocument.CreateZero(CanDeviceCount, ParCount);
        }

        public static void Sync(SFMDocument from, SFMDocument to)
        {
            App.UIDispatcherDoAction(() =>
            {
                for (int i = 0; i < to.Devices.Length; i++)
                {
                    for (int j = 0; j < to.Devices[i].Parameters.Length; j++)
                    {
                        to.Devices[i].Parameters[j].Value = from.Devices[i].Parameters[j].Value;
                    }
                }
            });
        }

        public static void SyncOneData(SFMDocument from, SFMDocument to, int DevIndex, int ParIndex)
        {
            if (to.Devices.Length > DevIndex && to.Devices[DevIndex].Parameters.Length > ParIndex)
            {
                App.UIDispatcherDoAction(() =>
                {
                    to.Devices[DevIndex].Parameters[ParIndex].Value = from.Devices[DevIndex].Parameters[ParIndex].Value;
                });
            }
        }

        public struct SyncOneDataNextRecvReqRsp
        {
            public int devIndex;
            public int parIndex;
            public decimal val;
        }

        public struct SyncOneDataNextRecvReqRspCb
        {
            public SyncOneDataNextRecvReqRsp pa;
            public Action<SyncOneDataNextRecvReqRsp> cb;
        }
        /// <summary>
        /// TODO:没有主动删除机制，当模块不在线时永远无法返回导致
        /// 数据一直存在再列表中
        /// </summary>
        public static List<SyncOneDataNextRecvReqRspCb> NextRecvSyncRecv = new List<SyncOneDataNextRecvReqRspCb>();
        public static void SyncOneDataOnNextRecv(SyncOneDataNextRecvReqRspCb rp)
        {
            NextRecvSyncRecv.Add(rp);
        }

        public static decimal GetOneData(int Dev, int Par)
        {
            return InherDoc.Devices[Dev].Parameters[Par].Value;
        }

        private static void Resolve(ref SFMDocument doc, CAN_OBJ info, ZhuDrive zhu)
        {
            PassivityDataFrame obj = (PassivityDataFrame)zhu.ObjDic[info.ID];
            obj.Data = info.data;
            switch (obj.CanID)
            {
                case 0x1A5:
                    {
                        ZhuDriveFaultCodeFrame df = (ZhuDriveFaultCodeFrame)obj;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[0].Value = df.FaultCode;
                    }
                    break;
                case 0x1A6:
                    {
                        ZhuDriveSWFrame df = (ZhuDriveSWFrame)obj;
                        for (int i = 0; i < 16; i++)
                        {
                            doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + i].Value = df.GetSW(i) ? 1 : 0;
                        }
                        for (int i = 0; i < 5; i++)
                        {
                            doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + 16 + i].Value = df.GetDrivers(i) ? 1 : 0;
                        }
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + 16 + 5].Value = df.Drive_State;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + 16 + 5 + 1].Value = df.Belt_HM;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + 16 + 5 + 2].Value = df.Traction_HM;
                    }
                    break;
                case 0x2A6:
                    {

                        ZhuDriveKeyswitchFrame df = (ZhuDriveKeyswitchFrame)obj;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[1 + 16 + 5 + 3].Value = df.Keyswitch_Voltage;//25
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 1].Value = df.Current_RMS;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 2].Value = df.Battery_Current;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 3].Value = df.Motor_RPM;//
                    }
                    break;
                case 0x3A6:
                    {
                        ZhuDriveStatusFrame df = (ZhuDriveStatusFrame)obj;
                        for (int i = 0; i < 7; i++)
                        {
                            doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 4 + i].Value = df.GetStatus(i);//
                        }
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 11].Value = df.WholeFault;//
                    }
                    break;
                case 0x4A6:
                    {
                        ZhuDriveGeneralHMFrame df = (ZhuDriveGeneralHMFrame)obj;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 12].Value = df.GeneralHM;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 13].Value = df.V1229731;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 14].Value = df.A;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 15].Value = df.BDIPercentage;
                    }
                    break;
                case 0x227:
                    {
                        ZhuDriveTrottleCommandFrame df = (ZhuDriveTrottleCommandFrame)obj;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 16].Value = df.启动泵 ? 1 : 0;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 17].Value = df.Handbrake_sw或低电量 ? 1 : 0;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 18].Value = df.无方向 ? 1 : 0;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 19].Value = df.Trottle_Command;//
                    }
                    break;
                case 0x1B1:
                    {
                        ZhuDriveSW2Frame df = (ZhuDriveSW2Frame)obj;
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + 0].Value = df.GetSW(0) ? 1 : 0;//
                        for (int i = 2; i < 8; i++)
                        {
                            doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + i - 1].Value = df.GetSW(i) ? 1 : 0;//
                        }
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + 7].Value = df.GetSW(13) ? 1 : 0;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + 8].Value = df.GetSW(14) ? 1 : 0;//
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + 9].Value = df.GetSW(15) ? 1 : 0;//

                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[25 + 20 + 10].Value = df.qM_ZONE;
                    }
                    break;

                default:
                    break;
            }



        }

        private static void Resolve(ref SFMDocument doc, CAN_OBJ info, Pump zhu)
        {
            PassivityDataFrame obj = (PassivityDataFrame)zhu.ObjDic[info.ID];
            obj.Data = info.data;
            switch (obj.CanID)
            {
                case 0x1A7:
                    {
                        ZhuDriveFaultCodeFrame df = (ZhuDriveFaultCodeFrame)obj;
                        doc.Devices[Pump.DeviceIndex].Parameters[0].Value = df.FaultCode;
                    }
                    break;
                case 0x1A8:
                    {
                        PumpSWFrame df = (PumpSWFrame)obj;
                        for (int i = 0; i < 16; i++)
                        {
                            doc.Devices[1].Parameters[1 + i].Value = df.GetSW(i) ? 1 : 0;
                        }
                        for (int i = 0; i < 5; i++)
                        {
                            doc.Devices[Pump.DeviceIndex].Parameters[1 + 16 + i].Value = df.GetDrivers(i) ? 1 : 0;
                        }
                        doc.Devices[Pump.DeviceIndex].Parameters[1 + 16 + 5].Value = df.Drive_State;
                        doc.Devices[Pump.DeviceIndex].Parameters[1 + 16 + 5 + 1].Value = 0;
                        doc.Devices[Pump.DeviceIndex].Parameters[1 + 16 + 5 + 2].Value = 0;
                    }
                    break;
                case 0x2A8:
                    {

                        ZhuDriveKeyswitchFrame df = (ZhuDriveKeyswitchFrame)obj;
                        doc.Devices[Pump.DeviceIndex].Parameters[1 + 16 + 5 + 3].Value = df.Keyswitch_Voltage;//25
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 1].Value = df.Current_RMS;//
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 2].Value = df.Battery_Current;//
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 3].Value = df.Motor_RPM;//
                    }
                    break;
                case 0x3A8:
                    {
                        ZhuDriveStatusFrame df = (ZhuDriveStatusFrame)obj;
                        for (int i = 0; i < 7; i++)
                        {
                            doc.Devices[Pump.DeviceIndex].Parameters[25 + 4 + i].Value = df.GetStatus(i);//
                        }
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 11].Value = df.WholeFault;//
                    }
                    break;
                case 0x4A8:
                    {
                        ZhuDriveGeneralHMFrame df = (ZhuDriveGeneralHMFrame)obj;
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 12].Value = df.GeneralHM;
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 13].Value = df.V1229731;
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 14].Value = df.A;
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 15].Value = df.BDIPercentage;
                    }
                    break;
                case 0x227:
                    {
                        //ZhuDriveTrottleCommandFrame df = (ZhuDriveTrottleCommandFrame)obj;
                        //doc.Devices[zhu.DeviceIndex].Parameters[25 + 16].Value = df.Trottle_Command;
                    }
                    break;
                case 0x2B1:
                    {
                        PumpDriveSW2Frame df = (PumpDriveSW2Frame)obj;
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 17 + 0].Value = df.GetSW(0) ? 1 : 0;//
                        for (int i = 2; i < 8; i++)
                        {
                            doc.Devices[Pump.DeviceIndex].Parameters[25 + 17 + i - 1].Value = df.GetSW(i) ? 1 : 0;//
                        }
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 17 + 7].Value = df.GetSW(13) ? 1 : 0;//
                        doc.Devices[Pump.DeviceIndex].Parameters[25 + 17 + 8].Value = df.GetSW(14) ? 1 : 0;//
                    }
                    break;

                default:
                    break;
            }
        }

        private static void Resolve(ref SFMDocument doc, CAN_OBJ info, BMS zhu)
        {
            PassivityDataFrame obj = (PassivityDataFrame)zhu.ObjDic[info.ID];
            obj.Data = info.data;
            switch (obj.CanID)
            {
                case 0x2F0:
                    {
                        BMS.MBS_2F0_DataFrame df = (BMS.MBS_2F0_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[0].Value = df.Ubus;
                        doc.Devices[BMS.DeviceIndex].Parameters[1].Value = df.IBattery;
                        doc.Devices[BMS.DeviceIndex].Parameters[2].Value = df.SOC;
                        doc.Devices[BMS.DeviceIndex].Parameters[3].Value = df.Capacity;

                        doc.Devices[BMS.DeviceIndex].Parameters[4].Value = df.OverVoltage ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[5].Value = df.CellLowVoltage ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[6].Value = df.DIFFERENCE ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[7].Value = df.OverallVoltageLow ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[8].Value = df.TempOutOfRange ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[9].Value = df.BatteryFault ? 1 : 0;
                        doc.Devices[BMS.DeviceIndex].Parameters[10].Value = df.ToShutdown ? 1 : 0;

                        doc.Devices[BMS.DeviceIndex].Parameters[11].Value = df.ErrorLv;
                    }
                    break;
                case 0x2F1:
                    {
                        BMS.MBS_2F1_DataFrame df = (BMS.MBS_2F1_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[12].Value = df.Umaxcell;
                        doc.Devices[BMS.DeviceIndex].Parameters[13].Value = df.UmaxcellPosition1;
                        doc.Devices[BMS.DeviceIndex].Parameters[14].Value = df.UmaxcellPosition2;
                        doc.Devices[BMS.DeviceIndex].Parameters[15].Value = df.Umincell;
                        doc.Devices[BMS.DeviceIndex].Parameters[16].Value = df.UmincellPosition1;
                        doc.Devices[BMS.DeviceIndex].Parameters[17].Value = df.UmincellPosition2;
                    }
                    break;
                case 0x2F2:
                    {
                        BMS.MBS_2F2_DataFrame df = (BMS.MBS_2F2_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[18].Value = df.Tmaxcell;
                        doc.Devices[BMS.DeviceIndex].Parameters[19].Value = df.TmaxcellPosition1;
                        doc.Devices[BMS.DeviceIndex].Parameters[20].Value = df.TmaxcellPosition2;
                        doc.Devices[BMS.DeviceIndex].Parameters[21].Value = df.Tmincell;
                        doc.Devices[BMS.DeviceIndex].Parameters[22].Value = df.TmincellPosition1;
                        doc.Devices[BMS.DeviceIndex].Parameters[23].Value = df.TmincellPosition2;
                    }
                    break;
                case 0x20A:
                    {
                        BMS.MBS_20A_DataFrame df = (BMS.MBS_20A_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[24].Value = df.CANCommNormal;
                    }
                    break;
                case 0x20B:
                    {
                        BMS.MBS_20B_DataFrame df = (BMS.MBS_20B_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[25].Value = df.PackParallelNumber;
                        doc.Devices[BMS.DeviceIndex].Parameters[26].Value = df.PackSeriesNumber;
                        doc.Devices[BMS.DeviceIndex].Parameters[27].Value = df.ChargerType;
                    }
                    break;
                case 0x326:
                    {
                        BMS.MBS_326_DataFrame df = (BMS.MBS_326_DataFrame)obj;
                        doc.Devices[BMS.DeviceIndex].Parameters[28].Value = df.MaxDischargeCurrent;
                        doc.Devices[BMS.DeviceIndex].Parameters[29].Value = df.MaxFeedbackCurrent;
                    }
                    break;

                default:
                    break;
            }
        }

        /// <summary>
        /// 检查是否需要主动返回
        /// </summary>
        /// <param name="pdevIndex"></param>
        /// <param name="pParIndex"></param>
        /// <param name="val"></param>
        private static void CheckReport(int pdevIndex, int pParIndex, int val)
        {
            List<int> RemoveList = new List<int>(4);
            for (int j = 0; j < NextRecvSyncRecv.Count; j++)
            {
                var pa = NextRecvSyncRecv[j].pa;
                if (pa.devIndex == pdevIndex && pa.parIndex == pParIndex)
                {
                    RemoveList.Add(j);
                    pa.val = val;
                    NextRecvSyncRecv[j].cb(pa);
                }
            }
            for (int k = RemoveList.Count - 1; k > 0; k--)
            {
                NextRecvSyncRecv.RemoveAt(k);
            }
        }


        public static int PumpHMI_Recv = 0;
        public static int ZhuHMI_Recv = 0;
        public static int CCC = 0;
        public static Action<ushort> PumpUpCmds;
        public static Action<ushort> ZhuUpCmds;
        public static Action<ushort> ZhuUpStatus;
        public static Action<ushort> PumpUpStatus;
        public static void Resolve(CAN_OBJ info)
        {
            CCC++;
            //Console.WriteLine($"{DateTime.Now.ToString("HH.mm.ss.fff")}  ResolveCount={CCC}");
            SFMDocument doc = InherDoc;
            if (ZhuDrive.CanIDList.Contains(info.ID))
            {
                ZhuDrive zhu = new ZhuDrive();
                Resolve(ref doc, info, zhu);

            }
            else if (Pump.CanIDList.Contains(info.ID))
            {
                Pump pump = new Pump();
                Resolve(ref doc, info, pump);

            }
            else if (BMS.CanIDList.Contains(info.ID))
            {
                BMS mbs = new BMS();
                Resolve(ref doc, info, mbs);

            }

            if (info.ID == ZhuDrive.ZhuDriveHMICanID)
            {
                ZhuHMI_Recv++;
                HMIHelper.HMIDateFrame fr = new HMIHelper.HMIDateFrame(info.data);
                // 60 + 250
                for (int i = 0; i < fr.ByteCount / 2; i++)
                {
                    ushort tmp = (ushort)(fr.Data0[i * 2] + fr.Data0[i * 2 + 1] * 256);
                    //TODO：根据功能码划分地址  fr.Can_Fc
                    ushort tmpaddr = (ushort)(fr.Addr_Start / 2+i);
                    //Console.WriteLine($"Zhu HMI Addr={tmpaddr}  Value={tmp}");
                    int paAddr = tmpaddr + ZhuDrive.HMIZhuDriveStart;
                    if (paAddr < doc.Devices[ZhuDrive.DeviceIndex].Parameters.Length)
                        doc.Devices[ZhuDrive.DeviceIndex].Parameters[paAddr].Value = tmp;

                    if (ZhuUpCmds!= null && paAddr == 128)
                    {
                        ZhuUpCmds(tmp);
                    }
                    if (ZhuUpStatus != null && paAddr == 141)
                    {
                        ZhuUpStatus(tmp);
                    }
                    
                    CheckReport(ZhuDrive.DeviceIndex, paAddr, tmp);
                }

                //Task t1 = new Task(() =>
                //{
                   
                //});
                //t1.Start();
                
            }
            else if (info.ID == Pump.PumpHMICanID)
            {
                PumpHMI_Recv++;
                HMIHelper.HMIDateFrame fr = new HMIHelper.HMIDateFrame(info.data);
                //TODO：根据功能码划分地址 fr.Can_Fc
                for (int i = 0; i < fr.ByteCount / 2; i++)
                {
                    ushort tmp = (ushort)(fr.Data0[i * 2] + fr.Data0[i*2 + 1] * 256);
                    ushort tmpaddr = (ushort)(fr.Addr_Start / 2+i);
                    //Console.WriteLine($"Pump HMI Addr={tmpaddr}  Value={tmp}");
                    int paAddr = tmpaddr + Pump.HMIPumpStart;
                    if (paAddr < doc.Devices[Pump.DeviceIndex].Parameters.Length)
                        doc.Devices[Pump.DeviceIndex].Parameters[paAddr].Value = tmp;
                    if (PumpUpCmds != null && paAddr == 128)
                    {
                        PumpUpCmds(tmp);
                    }
                    if (PumpUpStatus != null && paAddr == 141)
                    {
                        PumpUpStatus(tmp);
                    }
                    

                    CheckReport(Pump.DeviceIndex, paAddr, tmp);
                }

                //Task t2 = new Task(() =>
                //{
                    
                //});
                //t2.Start();
                
            }

            //包括Can直接传递的
            // Fault Code 
            // Whole Fault
            // 故障字1+故障字2
            if (ErrHisHelper.ErrCanIDs.Contains(info.ID))
            {
                ErrHisHelper err = new ErrHisHelper();
                err.Resolve(ref doc, info);
            }

            //Console.WriteLine($"{DateTime.Now.ToString("HH.mm.ss.fff")}  ZhuHMI_Recv={ZhuHMI_Recv} PumpHMI_Recv={PumpHMI_Recv}");
        }

    }
}
